library ieee;
use ieee.std_logic_1164.all;

entity controller_tb is
end controller_tb;

architecture behav of controller_tb is
    component controller is
        port(
        Op, Funct: in std_logic_vector(5 downto 0);
        MemToReg, MemWrite, Branch, AluSrc, RegDst, RegWrite, Jump: out std_logic;
        AluControl: out std_logic_vector(2 downto 0)
        );
    end component;

    signal Op_s, Funct_s: std_logic_vector(5 downto 0);
    signal MemToReg_s, MemWrite_s, Branch_s, AluSrc_s, RegDst_s, RegWrite_s,
           Jump_s: std_logic;
    signal AluControl_s: std_logic_vector(2 downto 0);

begin
    Con0: controller port map(Op_s, Funct_s, MemToReg_s, MemWrite_s, Branch_s,
                     AluSrc_s, RegDst_s, RegWrite_s, Jump_s,
                     AluControl_s);
    process
        -- maindec input
        type pattern1 is array(natural range <>) of std_logic_vector(5 downto 0);
        -- maindec output
        type pattern2 is array(natural range <>) of std_logic_vector(8 downto 0);
        -- aludec input
        type pattern3 is array(natural range <>) of std_logic_vector(5 downto 0);
        -- aludec output
        type pattern4 is array(natural range <>) of std_logic_vector(2 downto 0);

        constant maindecIn: pattern1:=("000000", "100011", "101011",
                                       "000100", "001000", "000010",
                                       "------", "------", "------");
        constant maindecOut: pattern2:=("000011010", "100101000", "010100000",
                                        "001000001", "000100000", "000000100",
                                        "---------", "---------", "---------");

        constant aludecIn: pattern3:=("100000", "------", "------",
                                      "------", "------", "------",
                                      "------", "100100", "101010");
        constant aludecOut: pattern4:=("010", "010", "010",
                                       "110", "010", "010",
                                       "---", "000", "111");
    begin
        for i in maindecIn'range loop
            Op_s <= maindecIn(i);
            Funct_s <= aludecIn(i);
            wait for 5 ns;
            assert MemToReg_s = maindecOut(i)(8)
                report "MemToReg! iteration: " & integer'image(i)
                severity error;
            assert MemWrite_s = maindecOut(i)(7)
                report "MemWrite! iteration: " & integer'image(i)
                severity error;
            assert RegDst_s = maindecOut(i)(6)
                report "Bad Branch! iteration: " & integer'image(i)
                severity error;
            assert AluSrc_s = maindecOut(i)(5)
                report "Bad AluSrc! iteration: " & integer'image(i)
                severity error;
            assert RegDst_s = maindecOut(i)(4)
                report "Bad RegDst! iteration: " & integer'image(i)
                severity error;
            assert RegWrite_s = maindecOut(i)(3)
                report "Bad RegWrite! iteration: " & integer'image(i)
                severity error;
            assert Jump_s = maindecOut(i)(2)
                report "Bad Jump! iteration: " & integer'image(i)
                severity error;
            assert AluControl_s = aludecOut(i)
                report "Bad AluControl! iteration: " & integer'image(i)
                severity error;
        end loop;
        assert False report "Test end." severity note;
        wait;
    end process;
end behav;
